package com.daxue.lcm.api.grpc.utis;

import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @author daxue0929
 * @date 2022/10/9
 */

public interface GrpcClientFunction<T, R>  {
    R apply(T t) throws Exception;

    default <V> GrpcClientFunction<V, R> compose(GrpcClientFunction<? super V, ? extends T> before) {
        return (V v) -> apply(Objects.requireNonNull(before).apply(v));
    }

    default <V> GrpcClientFunction<T, V> andThen(GrpcClientFunction<? super R, ? extends V> after) {
        return (T t) -> Objects.requireNonNull(after).apply(apply(t));
    }

    default GrpcClientFunction<T, R> withRetry(int maxAttempts, Predicate<Throwable>... include) {
        return (T t) -> {
            int attempts = 1;
            while (attempts < maxAttempts) {
                try {
                    return apply(t);
                } catch (Throwable e) {
                    if (Stream.of(include).noneMatch(p -> p.test(e))) {
                        throw e;
                    }
                    attempts++;
                }
            }
            return apply(t);
        };
    }


}
